// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CResolvedItemList.
//   $Id$



#include "stdafx.h"
#include "resolveditemlist.h"
#include "resolvedItem.h"
#include "isEqualNode.h"


CResolvedItemList::CResolvedItemList(void)
	:m_pTopList(this)
{
}

CResolvedItemList::~CResolvedItemList(void)
{
	while(!m_ResolvedItems.IsEmpty())
	{
		try
		{
			delete m_ResolvedItems.RemoveHead();
		}
		catch(...){ASSERT(0);}
	}
}

// creates and inserts a new item into the list.
CResolvedItem * CResolvedItemList::InsertNewItem(CResolvedItem * pItemBefore,long lId)
{
	CResolvedItem * pReturn = new CResolvedItem(this);
	if(pItemBefore)
	{
		POSITION pos = m_ResolvedItems.Find(pItemBefore);
		if(pos)
			m_ResolvedItems.InsertAfter(pos,pReturn);
		else
		{
			//Failed to insert into list, delete the 
			//	created item and null it for returning.
			delete pReturn;
			pReturn = 0;
		}
	}
	else
	{
		m_ResolvedItems.AddTail(pReturn);
	}
	m_mapItems.SetAt(reinterpret_cast<void*>(lId),pReturn);
	return pReturn;
}

// removes and deletes an item from the list and memory.
bool CResolvedItemList::RemoveItem(CResolvedItem * pItem)
{
	ASSERT(pItem != NULL);
	bool bOut = false;
	POSITION pos = m_ResolvedItems.Find(pItem);
	if(pos)
	{
		bOut = true; 
		m_ResolvedItems.RemoveAt(pos);
		DeselectItem(pItem);
		m_mapItems.RemoveKey(reinterpret_cast<void*>(pItem->m_lId));
		delete pItem;
	}

	return bOut;
}

// for the purposes of resolving the value of a list, stores pointers to any selected items in the list
HRESULT CResolvedItemList::SelectItem(CResolvedItem * pItem)
{
	HRESULT hr = S_FALSE;
	//Don't add if already in the list.
	if(m_SelectedItems.Find(pItem) == NULL) {
		//append the selected item to the list of selected items.
		m_SelectedItems.AddTail(pItem);
		hr = S_OK;
	}
	return hr;
}

// removes an item from the selcted items list.
HRESULT CResolvedItemList::DeselectItem(CResolvedItem * pItem)
{
	HRESULT hr = S_FALSE;
	//locate the item
	POSITION pos = m_SelectedItems.Find(pItem);
	if(pos)
	{
		m_SelectedItems.RemoveAt(pos);
		hr = S_OK;
	}
	return hr;
}

// Fills a given node pParentNode with the concatenated values of all selected items in this list.
HRESULT CResolvedItemList::GetSelectedValue(IXMLDOMNode* pParentNode)
{
	//Don't calll with NULL
	ASSERT(pParentNode != NULL);
	HRESULT hr = S_FALSE;
	POSITION pos = m_SelectedItems.GetHeadPosition();
	VARIANT vt;
	while(pos)
	{
		CResolvedItem * pItem = m_SelectedItems.GetNext(pos);
		pItem->get_value(&vt);
		switch(vt.vt)
		{
			case VT_DISPATCH:
			{
				CComQIPtr<IXMLDOMNode> pNewChild = vt.pdispVal;
				pParentNode->appendChild(pNewChild,0);
				break;
			}
			case VT_I4:
			{
				CResolvedItemList * pChildList = reinterpret_cast<CResolvedItemList *>(vt.lVal);
				pChildList->GetSelectedValue(pParentNode);
				break;
			}
			case VT_BSTR:
			{
				//??? awaiting poll result.
			}
		}
	}
	return hr;
}

// inspects the ResolvedItems, seeing if any match any of the nodes in the given list.
void CResolvedItemList::FindAndSelect(CTypedPtrList<CPtrList, IXMLDOMNode* >& lstNodes)
{
	POSITION posNodes = lstNodes.GetHeadPosition();
	POSITION posItems =	m_ResolvedItems.GetHeadPosition();
	VARIANT vtVal;
	while(posNodes && posItems)
	{
		CResolvedItem * pItem = m_ResolvedItems.GetAt(posItems);
		pItem->get_value(&vtVal);
		switch(vtVal.vt)
		{
			case VT_DISPATCH:
			{
			}
			case VT_I4:
			{
			}
			case VT_BSTR:
			{
			}
		}
	}
}
